// generating config files for a logical node
// Created: Apr. 14, 2023 by SUN Yazhou, asia.rabbit@163.com
// Last modified: Sep. 27, 2024 by SUN Yazhou, asia.rabbit@163.com

#include <iostream>
#include <cstring>
#include "Port.h"

using std::cerr;
using std::endl;

Port::Port(bool isin, bool isshm, int lnid, int portid) : fIsIn(isin), fIsShm(isshm),
  fLnId(lnid), fPortId(portid), fLnId1(-1), fIPPort(""), fStreamType(STREAM_OTHER){}
Port::~Port(){}

// set IP:port for transmit node only
// whether the source port is from CMC
void Port::SetTsmIPPort(const char *ipDst, const char *ipSrc, bool isCMCSrc){
  int port;
  // ip xxx.xxx.xxx.x0y; i=8y0[012]
  if(isCMCSrc) sscanf(ipDst, "%*d.%*d.%*d.%d", &port);
  else sscanf(ipSrc, "%*d.%*d.%*d.%d", &port);
  // port = 8000 + (port%10)*100; // 8y00 - data -- Port too limited
  port = 8000 + (port%100)*10; // 8yy0 - data -- Sep. 27, 2024
  if(StreamType() == CMD) port += 1; // cmd
  if(StreamType() == STA) port += 2; // status

  sprintf(fIPPort, "%s:%d", ipDst, port);
} // end member function SetIP

void Port::SetRcvIPPort(const char *ipp){ // set to transmit's
  strcpy(fIPPort, ipp);
} // end member function SetRcvIPPort


ofstream &operator<<(ofstream &fout, const Port &port){
  char par[128]{};
  if(port.fIsShm){ // shm
    if(port.fLnId1 < 0){
      cerr << "lnId: " << port.fLnId << " portId: " << port.fPortId << endl;
      cerr << "port info mismatch" << endl; getchar();
      exit(-1);
    } // end inner if
    if(port.fIsIn) sprintf(par, "shm_%d_%d", port.fLnId1, port.fLnId);
    else sprintf(par, "shm_%d_%d", port.fLnId, port.fLnId1);
  } // end if
  else strcpy(par, port.fIPPort); // socket

  fout << "[Stream0Ln" << port.fLnId << "Port" << port.fPortId << "]" << endl;
  fout << "direction=" << (port.fIsIn ? "input" : "output") << endl;
  fout << "type=" << (port.fIsShm ? "shm" : "socket") << endl;
  fout << "parameter=" << par << endl;

  return fout;
} // end friend funtion operator<<
